﻿
using SIG.Basic.Extensions;
using SIG.Data.Repositories.Case;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Infrastructure.Logging;
using SIG.Model.Case;
using SIG.Resources.Admin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace SIG.Service.Case
{
    public class WorkService : EntityService<Work>, IWorkService
    {

        private readonly IWorkRepository _articleRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public WorkService(IWorkRepository articleRepository, ILoggingService loggingService, ICacheService cacheService)
            : base(articleRepository, cacheService, loggingService)
        {

            _articleRepository = articleRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }

        public async Task<IList<Work>> GetActiveElementsAync(CancellationToken cancellationToken = default(CancellationToken))
        {
            //get list
            var key = $"{EntityNames.Work}_List_Active";

            IList<Work> articlelist;
            if (SettingsManager.Case.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    articlelist = (IList<Work>)_cacheService.Get(key);

                }
                else
                {
                    var article = await _articleRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.WorkTypes);
                    articlelist = article.ToList();
                    _cacheService.Set(key, articlelist, SettingsManager.Case.CacheDuration);
                }
            }
            else
            {
                var articles = await _articleRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.WorkTypes);
                articlelist = articles.ToList();
            }

            return articlelist;

        }



        public Work GetWorkDetail(int id)
        {
            return _articleRepository.GetFirstOrDefault(m => m.Id == id, m => m.WorkTypes);
        }

        public List<Work> GetPagedActiveElements(int pageIndex, int pageSize, string keyword, int? typeId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Work}_ListCount_Active_{keyword}_{typeId}";

            var totalIQuery = _articleRepository.GetAllElements().Where(g => g.Active);
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (typeId > 0)
                totalIQuery = totalIQuery.Where(g => g.WorkTypes.Any(t => t.Id == typeId));

            if (SettingsManager.Case.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Case.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Work}_List_Active_{pageIndex}_{pageSize}_{keyword}_{typeId}";

            List<Work> article;
            Expression<Func<Work, bool>> filter = g => g.Active;
            Expression<Func<Work, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Work, bool>> filterByCategory = g => g.WorkTypes.Any(t => t.Id == typeId);

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (typeId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Case.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    article = (List<Work>)_cacheService.Get(key);

                }
                else
                {
                    article = _articleRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.WorkTypes).ToList();
                    _cacheService.Set(key, article, SettingsManager.Case.CacheDuration);
                }
            }
            else
            {
                article = _articleRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.WorkTypes).ToList();
            }

            return article;

        }





   



        public List<Work> GetPagedElements(int pageIndex, int pageSize, string keyword, int? typeId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Work}_ListCount_{keyword}_{typeId}";

            var totalIQuery = _articleRepository.GetAllElements();
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (typeId > 0)
                totalIQuery = totalIQuery.Where(g => g.WorkTypes.Any(t => t.Id == typeId));

            if (SettingsManager.Case.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Case.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Work}_List_{pageIndex}_{pageSize}_{keyword}_{typeId}";

            List<Work> articles;
            Expression<Func<Work, bool>> filter = g => true;
            Expression<Func<Work, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Work, bool>> filterByCategory = g => g.WorkTypes.Any(t => t.Id == typeId);

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (typeId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Case.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    articles = (List<Work>)_cacheService.Get(key);
                }
                else
                {
                    articles = _articleRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.WorkTypes).ToList();
                    _cacheService.Set(key, articles, SettingsManager.Case.CacheDuration);
                }
            }
            else
            {
                articles = _articleRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.WorkTypes).ToList();
            }

            return articles;

        }



        public IEnumerable<Work> RecommendWorks(int count)
        {
            var key = $"{EntityNames.Work}s_Recommend";

            if (!SettingsManager.Case.EnableCaching)
            {
                return _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active && p.Recommend, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Work>)_cacheService.Get(key);

            }

            var articleList = _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active && p.Recommend, false).ToList();
            _cacheService.Set(key, articleList, SettingsManager.Case.CacheDuration);


            return articleList;
        }
        public IEnumerable<Work> LatesterWorks(int count)
        {
            var key = $"{EntityNames.Work}s_Latester_{count}";

            if (!SettingsManager.Case.EnableCaching)
            {
                return _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Work>)_cacheService.Get(key);

            }

            var articleList = _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            _cacheService.Set(key, articleList, SettingsManager.Case.CacheDuration);


            return articleList;
        }
        public IEnumerable<Work> LatesterWorks(int count, int typeId)
        {
            if (typeId == 0)
                return LatesterWorks(count);

            var key = $"{EntityNames.Work}s_Latester_{count}_{typeId}";
            if (!SettingsManager.Case.EnableCaching)
            {
                return _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.WorkTypes.Any(t=>t.Id == typeId), false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Work>)_cacheService.Get(key);

            }

            var articleList = _articleRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.WorkTypes.Any(t => t.Id == typeId), false).ToList();
            _cacheService.Set(key, articleList, SettingsManager.Case.CacheDuration);


            return articleList;
        }


    }
}
